import { Injectable, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { zip } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { MenuService, SettingsService, TitleService, ALAIN_I18N_TOKEN, Menu } from '@delon/theme';
import { ACLService } from '@delon/acl';
import { TranslateService } from '@ngx-translate/core';
import { I18NService } from '../i18n/i18n.service';

import { NzIconService } from 'ng-zorro-antd';
import { ICONS_AUTO } from '../../../style-icons-auto';
import { ICONS } from '../../../style-icons';
import { environment } from '@env/environment';
import { ITokenService, DA_SERVICE_TOKEN } from '@delon/auth';
import { menus } from '../../menu';
import { SubdomainTenancyNameFinder } from '@shared';

/**
 * 用于应用启动时
 * 一般用来获取应用所需要的基础数据等
 */
@Injectable()
export class StartupService {
  constructor(
    iconSrv: NzIconService,
    private menuService: MenuService,
    private translate: TranslateService,
    @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
    private settingService: SettingsService,
    private aclService: ACLService,
    private titleService: TitleService,
    private httpClient: HttpClient,
    @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService,
  ) {
    iconSrv.addIcon(...ICONS_AUTO, ...ICONS);
    // 随意设置一个无效的token，以允许 load() 获取数据: https://ng-alain.com/auth/getting-started/zh
    const token = tokenService.get();
    if (!token.token) {
      tokenService.set({ token: 'empty' });
    }
  }

  load(): Promise<any> {
    let tenancyFinder = new SubdomainTenancyNameFinder();
    const tenancyName = tenancyFinder.getCurrentTenancyNameOrNull();

    if (tenancyName == null) {
      environment.SERVER_URL = environment.SERVER_URL.replace(tenancyFinder.tenancyNamePlaceHolderInUrl + '.', '');
      environment.IDENTITY_URL = environment.IDENTITY_URL.replace(tenancyFinder.tenancyNamePlaceHolderInUrl + '.', '');
    } else {
      environment.SERVER_URL = environment.SERVER_URL.replace(tenancyFinder.tenancyNamePlaceHolderInUrl, tenancyName);
      environment.IDENTITY_URL = environment.IDENTITY_URL.replace(tenancyFinder.tenancyNamePlaceHolderInUrl, tenancyName);
    }

    // only works with promises
    // https://github.com/angular/angular/issues/15088
    return new Promise(resolve => {
      zip(
        this.httpClient.get(`/assets/i18n/${this.i18n.defaultLang}.json`),
        this.httpClient.get(`${environment.SERVER_URL}/config/GetAll`),
        this.httpClient.get(`${environment.IDENTITY_URL}/account/userinfo`),
      )
        .pipe(
          // 接收其他拦截器后产生的异常消息
          catchError(([langData, appData, userInfo]) => {
            resolve(null);
            return [langData, appData, userInfo];
          }),
        )
        .subscribe(
          ([langData, appData, userInfo]) => {
            // setting language data
            this.translate.setTranslation(this.i18n.defaultLang, langData);
            this.translate.setDefaultLang(this.i18n.defaultLang);

            // application data
            const res: any = appData;
            // 应用信息：包括站点名、描述、年份
            this.settingService.setApp({
              name: res.app.name,
              description: res.app.description,
            });
            // 用户信息：包括姓名、头像、邮箱地址
            this.settingService.setUser(userInfo);
            // ACL：设置权限为全量
            let roles = res.roles || [];
            this.aclService.setRole(roles);
            // 初始化菜单
            StartupService.filterMenu(menus, roles);
            this.menuService.add(menus);
            // 设置页面标题的后缀
            this.titleService.default = '';
            this.titleService.suffix = res.app.name;
          },
          () => { },
          () => {
            resolve(null);
          },
        );
    });
  }

  private static filterMenu(items: Menu[], roles: string[]) {
    for (let item of items) {
      if (item.acl) {
        item.hide = roles.indexOf(item.acl) >= 0;
        if (item.children && item.children.length > 0) {
          StartupService.filterMenu(item.children, roles);
        }
      }
    }
  }

  private static getDocumentOrigin() {
    if (!document.location.origin) {
      return (
        document.location.protocol +
        '//' +
        document.location.hostname +
        (document.location.port ? ':' + document.location.port : '')
      );
    }

    return document.location.origin;
  }
}
